package com.buanalintas.sandals.pos.request;

import com.buanalintas.bynga.Access;
import com.buanalintas.bynga.Action;
import com.buanalintas.bynga.Controller;
import com.buanalintas.bynga.Dictionary;
import com.buanalintas.bynga.Field;
import com.buanalintas.bynga.Logger;
import com.buanalintas.bynga.Page;
import com.buanalintas.bynga.Persistence;
import com.buanalintas.bynga.Sequence;
import com.buanalintas.bynga.Template;
import com.buanalintas.bynga.Utility;
import com.buanalintas.bynga.formatter.DateFormatter;
import com.buanalintas.sandals.pos.entities.PosMasterItemStock;
import com.buanalintas.sandals.pos.entities.PosMasterStatus;
import com.buanalintas.sandals.pos.entities.PosTransactionDistribution;
import com.buanalintas.sandals.pos.entities.PosTransactionDistributionDetail;
import com.buanalintas.sandals.pos.entities.PosTransactionItemStock;
import com.buanalintas.sandals.pos.entities.PosTransactionRequest;
import com.buanalintas.sandals.pos.entities.PosTransactionRequestDetail;
import com.buanalintas.sandals.pos.item.Item;
import com.buanalintas.sandals.pos.requestdetail.RequestDetail;
import com.buanalintas.sandals.pos.status.Status;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.List;
import javax.persistence.EntityManager;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Request extends Page {

    private Field requestId;
    private Field requestUserId;
    private Field requestUnitId;
    private Field requestNumber;
    private Field requestDate;
    private Field requestNeededDate;
    private Field requestDescription;
    private Field requestProgress;
    private Field requestRejectReason;
    private Field requestTimestamp;
    private Action actionRevision = new Action("revisi", "Revision Request");
    private Action actionReject = new Action("reject", "Reject Request");
    private Action actionAgree = new Action("approve", "Agree Request");

    public Request() {
        super();

        setTheClass(PosTransactionRequest.class);
        setPageDetail(RequestDetail.class);

        requestId = new Field();
        requestId.setName("requestId");
        requestId.setCaption("id");
        requestId.setListProperties("");
        requestId.setInputProperties("");
        getFields().add(requestId);

        requestUserId = new Field();
        requestUserId.setName("requestUserId");
        requestUserId.setCaption("user");
        requestUserId.setListProperties("");
        requestUserId.setInputProperties(" size=\"20\" readonly");
        getFields().add(requestUserId);

        requestUnitId = new Field();
        requestUnitId.setName("requestUnitId");
        requestUnitId.setCaption("unit");
        requestUnitId.setListProperties("");
        requestUnitId.setInputProperties(" size=\"20\" readonly");
        getFields().add(requestUnitId);

        requestNumber = new Field();
        requestNumber.setName("requestNumber");
        requestNumber.setCaption("number");
        requestNumber.setListProperties(" align=\"center\" width=\"15%\" nowrap");
        requestNumber.setInputProperties(" size=\"20\" readonly");
        requestNumber.setRequired(true);
        getFields().add(requestNumber);

        requestDate = new Field();
        requestDate.setName("requestDate");
        requestDate.setCaption("date");
        requestDate.setListProperties(" align=\"center\" width=\"8%\" nowrap");
        requestDate.setInputProperties(" size=\"8\" readonly");
        requestDate.setDefaultValue(Utility.getTimestamp());
        getFields().add(requestDate);

        requestNeededDate = new Field();
        requestNeededDate.setName("requestNeededDate");
        requestNeededDate.setCaption("needed date");
        requestNeededDate.setListProperties(" align=\"center\" width=\"8%\" nowrap");
        requestNeededDate.setInputProperties(" size=\"8\" readonly");
        getFields().add(requestNeededDate);

        requestDescription = new Field();
        requestDescription.setName("requestDescription");
        requestDescription.setCaption("description");
        requestDescription.setListProperties(" width=\"49%\"");
        requestDescription.setInputProperties(" cols=\"50\" rows=\"5\"");
        requestDescription.setInputType(Field.INPUT_TEXT_AREA);
        requestDescription.setInputCase(Field.CASE_UPPER);
        getFields().add(requestDescription);

        requestProgress = new Field();
        requestProgress.setName("requestProgress");
        requestProgress.setCaption("status");
        requestProgress.setListProperties(" align=\"center\" width=\"10%\" nowrap");
        requestProgress.setInputProperties("");
        requestProgress.setInputType(Field.INPUT_COMBO_BOX);
        requestProgress.getOptions().add(new String[]{"1", "New"});
        requestProgress.getOptions().add(new String[]{"2", "Revision"});
        requestProgress.getOptions().add(new String[]{"3", "Rejected"});
        requestProgress.getOptions().add(new String[]{"4", "Approved"});
        getFields().add(requestProgress);

        requestRejectReason = new Field();
        requestRejectReason.setName("requestRejectReason");
        requestRejectReason.setCaption("reason");
        requestRejectReason.setListProperties(" width=\"10%\" nowrap");
        requestRejectReason.setInputProperties("");
        requestRejectReason.setInputCase(Field.CASE_UPPER);
        getFields().add(requestRejectReason);

        requestTimestamp = new Field();
        requestTimestamp.setName("requestTimestamp");
        requestTimestamp.setCaption("timestamp");
        requestTimestamp.setListProperties(" align=\"center\" width=\"1%\" nowrap");
        requestTimestamp.setInputProperties(" size=\"20\" readonly");
        requestTimestamp.setDefaultValue(Utility.getTimestamp());
        getFields().add(requestTimestamp);

        getActions().add(Action.TRANS_ADD);
        getActions().add(Action.TRANS_EDIT);
        getActions().add(Action.TRANS_VIEW);
        fillFields();

        getFieldsAdd().clear();
        getFieldsAdd().add(requestNumber);
        getFieldsAdd().add(requestDate);
        getFieldsAdd().add(requestNeededDate);
        getFieldsAdd().add(requestDescription);

        getFieldsEdit().clear();
        getFieldsEdit().add(requestNumber);
        getFieldsEdit().add(requestDate);
        getFieldsEdit().add(requestNeededDate);
        getFieldsEdit().add(requestDescription);

        getFieldsList().clear();
        getFieldsList().add(requestNumber);
        getFieldsList().add(requestDate);
        getFieldsList().add(requestUnitId);
        getFieldsList().add(requestNeededDate);
        getFieldsList().add(requestProgress);
        getFieldsList().add(requestRejectReason);
        getFieldsList().add(requestDescription);

        getFieldsView().clear();
        getFieldsView().add(requestNumber);
        getFieldsView().add(requestNeededDate);
        getFieldsView().add(requestDescription);
        getFieldsView().add(requestProgress);
        getFieldsView().add(requestRejectReason);
        getFieldsView().add(requestUserId);
        getFieldsView().add(requestUnitId);
        getFieldsView().add(requestTimestamp);

        setController(new RequestController(this));

        getActions().add(actionRevision);
        getActions().add(actionAgree);
        getActions().add(actionReject);

        setExportList(getClass().getResourceAsStream("RequestList.jasper"));
        setExport(getClass().getResourceAsStream("Request.jasper"));
    }

    @Override
    public void afterInit(HttpServletRequest req, HttpServletResponse res) {
        requestNeededDate.setFormater(DateFormatter.getInstanceDate(this));
        requestTimestamp.setFormater(DateFormatter.getInstanceDateTime(this));
    }

    @Override
    public void beforeAdd() {
        requestNumber.setDefaultValue(generate());
    }

    @Override
    public void beforeList() {
        if (!getCurrentUnit().getUnitId().equals(1)) {
            getController().setCondition("t.requestUnitId.unitId=" + getCurrentUnit().getUnitId());
        }
    }

    @Override
    public String addJavascript() {
        return "<script>function __revision(id) {var reason = prompt('" + Dictionary.getValue(this, "Enter revision reason") + "?', ''); if (reason != null) { location.href = \"?m=" + getMenu().getMenuName() + "&a=" + actionRevision.getName() + "&id=\"+id+\"&reason=\"+escape(reason); } return false; };function __reject(id) {var reason = prompt('" + Dictionary.getValue(this, "Enter rejected reason") + "?', ''); if (reason != null) { location.href = \"?m=" + getMenu().getMenuName() + "&a=" + actionReject.getName() + "&id=\"+id+\"&reason=\"+escape(reason); } return false; }</script>";
    }

    @Override
    public boolean isGranted(Action action, Object data) {
        boolean granted = super.isGranted(action, data);
        if (granted) {
            PosTransactionRequest request = (PosTransactionRequest) data;
            if (action.equals(Action.EDIT) || action.equals(Action.TRANS_EDIT) || action.equals(Action.DELETE)) {
                granted = request.getRequestProgress() == null || request.getRequestProgress().equals("1") || request.getRequestProgress().equals("2");
            }
        }
        return granted;
    }

    @Override
    public String delete(Object data) {
        String delete = super.delete(data);
        if (delete == null) {
            PosTransactionRequest request = (PosTransactionRequest) data;
            if (!"1".equals(request.getRequestProgress())) {
                delete = Dictionary.getValue(this, "can not be deleted");
            }
        }
        return delete;
    }

    @Override
    public StringBuffer processCustomRowCommand(StringBuffer template, Page page, Object data) {
        StringBuffer commands = new StringBuffer();
        StringBuffer command = null;
        PosTransactionRequest request = (PosTransactionRequest) data;
        if (request.getRequestProgress() == null || request.getRequestProgress().equals("1")) {
            if (Access.isGranted(page, actionRevision)) {
                command = new StringBuffer(template.toString());
                Utility.replaceAll(command, Template.TABLE_ROW_MENU_COMMAND_CUSTOM_LINK, "?m=" + page.getMenu().getMenuName() + "&a=" + actionRevision.getName() + "&id=" + Utility.encode(Utility.getStringValue(data, page.getPrimaryKeyField())));
                Utility.replaceAll(command, Template.TABLE_ROW_MENU_COMMAND_CUSTOM_TITLE, Dictionary.getValue(page, "Revision request"));
                Utility.replaceAll(command, Template.TABLE_ROW_MENU_COMMAND_CUSTOM_PROPERTIES, " onclick=\"return __revision('" + Utility.encode(Utility.getStringValue(data, page.getPrimaryKeyField())) + "')\"");
                Utility.replaceAll(command, Template.TABLE_ROW_MENU_COMMAND_CUSTOM_IMAGE, "?image=command-revision.png");
                commands.append(command.toString());
            }
            if (Access.isGranted(page, actionReject)) {
                command = new StringBuffer(template.toString());
                Utility.replaceAll(command, Template.TABLE_ROW_MENU_COMMAND_CUSTOM_LINK, "?m=" + page.getMenu().getMenuName() + "&a=" + actionReject.getName() + "&id=" + Utility.encode(Utility.getStringValue(data, page.getPrimaryKeyField())));
                Utility.replaceAll(command, Template.TABLE_ROW_MENU_COMMAND_CUSTOM_TITLE, Dictionary.getValue(page, "Reject request"));
                Utility.replaceAll(command, Template.TABLE_ROW_MENU_COMMAND_CUSTOM_PROPERTIES, " onclick=\"return __reject('" + Utility.encode(Utility.getStringValue(data, page.getPrimaryKeyField())) + "')\"");
                Utility.replaceAll(command, Template.TABLE_ROW_MENU_COMMAND_CUSTOM_IMAGE, "?image=command-reject.png");
                commands.append(command.toString());
            }
            if (Access.isGranted(page, actionAgree)) {
                command = new StringBuffer(template.toString());
                Utility.replaceAll(command, Template.TABLE_ROW_MENU_COMMAND_CUSTOM_LINK, "?m=" + page.getMenu().getMenuName() + "&a=" + actionAgree.getName() + "&id=" + Utility.encode(Utility.getStringValue(data, page.getPrimaryKeyField())));
                Utility.replaceAll(command, Template.TABLE_ROW_MENU_COMMAND_CUSTOM_TITLE, Dictionary.getValue(page, "Approve request"));
                Utility.replaceAll(command, Template.TABLE_ROW_MENU_COMMAND_CUSTOM_PROPERTIES, " onclick=\"return confirm('" + Dictionary.getValue(page, "Approve request") + "?')\"");
                Utility.replaceAll(command, Template.TABLE_ROW_MENU_COMMAND_CUSTOM_IMAGE, "?image=command-approve.png");
                commands.append(command.toString());
            }
        }
        return commands;
    }

    @Override
    public String doAction() {

        String id = Utility.decode(Utility.getParameter(getRequest(), "id"));
        if (id != null && !id.trim().equals("")) {
            PosTransactionRequest data = (PosTransactionRequest) getController().getData(id);
            if (getAction().equals(actionRevision)) {
                String reason = Utility.getParameter(getRequest(), "reason");
                if (reason == null || reason.trim().equals("")) {
                    return "err:" + Dictionary.getValue(this, "Please enter revision reason");
                }
                try {
                    data.setRequestProgress("2");
                    data.setRequestRejectReason(Utility.getParameter(getRequest(), "reason"));
                    getController().update(data);
                    return "ok:" + Dictionary.getValue(this, "Data with") + " " + getObjectInfo(data) + " " + Dictionary.getValue(this, "rejected succesfully");
                } catch (Exception e) {
                    Logger.getInstance().log(e);
                    return "err:" + Dictionary.getValue(this, "Data with") + " " + getObjectInfo(data) + " " + Dictionary.getValue(this, "rejected failed") + ": " + e.getMessage();
                }
            } else if (getAction().equals(actionReject)) {
                String reason = Utility.getParameter(getRequest(), "reason");
                if (reason == null || reason.trim().equals("")) {
                    return "err:" + Dictionary.getValue(this, "Please enter rejected reason");
                }
                try {
                    data.setRequestProgress("3");
                    data.setRequestRejectReason(Utility.getParameter(getRequest(), "reason"));
                    getController().update(data);
                    return "ok:" + Dictionary.getValue(this, "Data with") + " " + getObjectInfo(data) + " " + Dictionary.getValue(this, "rejected succesfully");
                } catch (Exception e) {
                    Logger.getInstance().log(e);
                    return "err:" + Dictionary.getValue(this, "Data with") + " " + getObjectInfo(data) + " " + Dictionary.getValue(this, "rejected failed") + ": " + e.getMessage();
                }
            } else if (getAction().equals(actionAgree)) {
                EntityManager em = getEntityManager();
                PosMasterStatus statusGood = Status.getStatusGood(em);
                try {
                    em.getTransaction().begin();
                    PosTransactionRequest request = (PosTransactionRequest) data;
                    List<PosTransactionRequestDetail> details = em.createQuery("SELECT t FROM PosTransactionRequestDetail t WHERE t.requestDetailRequestId.requestId='" + id + "'").setHint(Persistence.REFRESH_HINT, true).getResultList();
                    PosTransactionDistribution requestDistribution = new PosTransactionDistribution();
                    requestDistribution.setDistributionId(Sequence.next(requestDistribution));
                    requestDistribution.setDistributionDate(Utility.getTimestamp());
                    requestDistribution.setDistributionNumber(generate());
                    requestDistribution.setDistributionUnitId(getCurrentUnit());
                    requestDistribution.setDistributionUserId(request.getRequestUserId());
                    requestDistribution.setDistributionTimestamp(Utility.getTimestamp());
                    requestDistribution.setDistributionDescription("Request By Unit " + request.getRequestUnitId().toString());
                    requestDistribution.setDistributionDestinationUnitId(request.getRequestUnitId());
                    requestDistribution.setDistributionNumber(generateDistribution(request.getRequestUnitId().toString()));
                    requestDistribution.setDistributionStatusId(statusGood);
                    requestDistribution.setDistributionProgress("5");
                    
                    for (PosTransactionRequestDetail detail : details) {
//                        PosMasterItemStock stockUnit = Item.getStock(em, detail.getRequestDetailItemId(), request.getRequestUnitId(), statusGood);
//                        PosMasterItemStock stockInventory = Item.getStock(em, detail.getRequestDetailItemId(), getCurrentUnit(), statusGood);

//                        PosMasterItemStock stockUnit = (PosMasterItemStock) em;
//                        PosMasterItemStock stockInventory = (PosMasterItemStock) em;
                        PosTransactionDistributionDetail requestDistributionDetail = new PosTransactionDistributionDetail();
//
//                        PosMasterItemStock stock = Item.getStock(em, detail.getRequestDetailItemId(), getCurrentUnit(), statusGood);
//                        PosMasterItemStock stock = (PosMasterItemStock) em;
//                        if (detail.getRequestDetailQuantity().compareTo(stock.getItemStockValue()) > 0) {
//                            detail.setRequestDetailDescription("Stock not enough, update request quantity from " + "" + detail.getRequestDetailQuantity() + "to" + "" + stock.getItemStockValue());
//                            detail.setRequestDetailQuantity(stock.getItemStockValue());
//                        }
                        
                        BigDecimal tot = BigDecimal.ZERO;
                        int qty = 0;
                        PosTransactionItemStock itemStock = new PosTransactionItemStock();

//                        Integer senderStock = stockInventory.getItemStockValue() - detail.getRequestDetailQuantity();
//
//                        itemStock.setItemStockId(Sequence.next(itemStock));
//                        itemStock.setItemStockItemId(detail.getRequestDetailItemId());
//                        itemStock.setItemStockSizeId(detail.getRequestDetailSizeId());
//                        itemStock.setItemStockUnitId(getCurrentUnit());
//                        itemStock.setItemStockStatusId(statusGood);
//                        itemStock.setItemStockType("8");
//                        itemStock.setItemStockLast(stockInventory.getItemStockValue());
//                        itemStock.setItemStockValue(detail.getRequestDetailQuantity());
//                        itemStock.setItemStockCurrent(stockInventory.getItemStockValue() - itemStock.getItemStockValue());
//                        itemStock.setItemStockUserId(getCurrentUser());
//                        itemStock.setItemStockTimestamp(Utility.getTimestamp());
//                        em.persist(itemStock);

//                        itemStocks.setItemStockId(Sequence.next(itemStocks));
//                        itemStocks.setItemStockItemId(detail.getRequestDetailItemId());
//                        itemStocks.setItemStockUnitId(getCurrentUnit());
//                        itemStocks.setItemStockStatusId(statusGood);
//                        itemStocks.setItemStockType("8");
//                        itemStocks.setItemStockLast(stockInventory.getItemStockValue());
//                        itemStocks.setItemStockValue(detail.getRequestDetailQuantity());
//                        itemStocks.setItemStockCurrent(stockInventory.getItemStockValue() - itemStocks.getItemStockValue());
//                        itemStocks.setItemStockUserId(getCurrentUser());
//                        itemStocks.setItemStockTimestamp(Utility.getTimestamp());
//                        em.persist(itemStocks);
                        qty = qty + detail.getRequestDetailQuantity();
                        
                        requestDistributionDetail.setDistributionDetailDistributionId(requestDistribution);
                        requestDistributionDetail.setDistributionDetailId(Sequence.next(requestDistributionDetail));
                        requestDistributionDetail.setDistributionDetailDescription("Request By Unit " + request.getRequestUnitId().toString());
                        requestDistributionDetail.setDistributionDetailItemId(detail.getRequestDetailItemId());
                        requestDistributionDetail.setDistributionDetailQuantity(detail.getRequestDetailQuantity());
                        requestDistributionDetail.setDistributionDetailSizeId(detail.getRequestDetailSizeId());
                        em.persist(requestDistributionDetail);

//                        stockUnit.setItemStockValue(destinationStock);
//                        stockInventory.setItemStockValue(senderStock);
                    }
////                    requestDistribution.setDistributionTotal(new BigDecimal(qty));
//                    requestDistribution.setDistributionPaid(BigDecimal.ZERO);
                    em.persist(requestDistribution);
                    request.setRequestProgress("4");
                    em.getTransaction().commit();
                } catch (Exception e) {
                    Logger.getInstance().log(e);
                    return "err:" + Dictionary.getValue(this, "Data with") + " " + getObjectInfo(data) + " " + Dictionary.getValue(this, "approved failed") + ": " + e.getMessage();
                }
            }
        }
        return null;
    }

    public String generateDistribution(String unitCode) {
        Calendar cal = Calendar.getInstance();
        String year = "" + cal.get(Calendar.YEAR);
        String month = Utility.intToRoman(cal.get(Calendar.MONTH) + 1);
        try {
            PosTransactionDistribution distribution = (PosTransactionDistribution) getEntityManager().createQuery("SELECT t FROM PosTransactionDistribution t WHERE t.distributionNumber LIKE '%/" + unitCode + "/DIS/%/" + year + "' ORDER BY t.distributionTimestamp DESC").setHint(Persistence.REFRESH_HINT, true).setFirstResult(0).setMaxResults(1).getSingleResult();
            return Utility.lpad(Integer.parseInt(distribution.getDistributionNumber().substring(0, 4)) + 1, 4, "0") + "/" + unitCode + "/DIS/" + month + "/" + year;
        } catch (Exception e) {
        }
        return "0001/" + unitCode + "/DIS/" + month + "/" + year;
    }

    class RequestController extends Controller {

        public RequestController(Page page) {
            super(page);
            setOrder(requestTimestamp);
            setOrderType("DESC");
        }

        @Override
        public void beforeInsert(Object data, List detail) {
            PosTransactionRequest request = (PosTransactionRequest) data;
            request.setRequestNumber(generate());
            request.setRequestProgress("1");
            request.setRequestUnitId(getCurrentUnit());
            request.setRequestUserId(getCurrentUser());
            request.setRequestTimestamp(Utility.getTimestamp());

//            for (int i = detail.size() - 1; i > 0; i--) {
//                PosTransactionRequestDetail d1 = (PosTransactionRequestDetail) detail.get(i);
//                for (int j = 0; j < i; j++) {
//                    PosTransactionRequestDetail d2 = (PosTransactionRequestDetail) detail.get(j);
//                    if (d2.getRequestDetailItemId().equals(d1.getRequestDetailItemId())) {
//                        d2.setRequestDetailQuantity(d2.getRequestDetailQuantity()+d1.getRequestDetailQuantity());
//                        detail.remove(i);
//                        break;
//                    }
//                }
//            }
        }

        @Override
        public void beforeUpdate(Object data, List list, List listDelete) {
            PosTransactionRequest request = (PosTransactionRequest) data;
            request.setRequestProgress("1");
            request.setRequestRejectReason(Dictionary.getValue(page, "Revision") + ": " + request.getRequestRejectReason());
        }
    }

    public String generate() {
        String unitCode = (getCurrentUnit()).getUnitCode();
        Calendar cal = Calendar.getInstance();
        String year = "" + cal.get(Calendar.YEAR);
        String month = Utility.intToRoman(cal.get(Calendar.MONTH) + 1);
        try {
            PosTransactionRequest request = (PosTransactionRequest) getEntityManager().createQuery("SELECT t FROM PosTransactionRequest t WHERE t.requestNumber LIKE '%/" + unitCode + "/REQ/%/" + year + "' ORDER BY t.requestTimestamp DESC").setHint(Persistence.REFRESH_HINT, true).setFirstResult(0).setMaxResults(1).getSingleResult();
            return Utility.lpad(Integer.parseInt(request.getRequestNumber().substring(0, 4)) + 1, 4, "0") + "/" + unitCode + "/REQ/" + month + "/" + year;
        } catch (Exception e) {
        }
        return "0001/" + unitCode + "/REQ/" + month + "/" + year;
    }

    @Override
    public void beforeExport() {
        getExportParams().put("title", Dictionary.getValue(this, "Request"));
    }

    @Override
    public void beforeExportMulti() {
        beforeExport();
    }
}
